/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.jena.riot;


import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Path;

import org.junit.jupiter.api.Test;

import org.apache.jena.atlas.lib.IRILib;
import org.apache.jena.atlas.lib.StrUtils;
import org.apache.jena.atlas.web.TypedInputStream;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.riot.adapters.RDFReaderFactoryRIOT;
import org.apache.jena.sparql.util.Context;
import org.apache.jena.util.FileUtils;

/* Test of integration with Jena via model.read.
 * Also tests triples format reading of RDFDataMgr */
public class TestJenaReaderRIOT
{
    private static final String directory = "testing/RIOT/Reader";

    private static Context context = new Context();

    @Test public void read_01() { jenaread("D.nt"); }
    @Test public void read_02() { jenaread("D.ttl"); }
    @Test public void read_03() { jenaread("D.rdf"); }
    @Test public void read_04() { jenaread("D.rdf"); }
    @Test public void read_05() { jenaread("D.rj"); }
    @Test public void read_06() { jenaread("D.jsonld"); }

    @Test public void read_11() { jenaread("D.nt",   "N-TRIPLES"); }
    @Test public void read_12() { jenaread("D.ttl",  "TTL"); }
    @Test public void read_13() { jenaread("D.rdf",  "RDF/XML"); }
    @Test public void read_14() { jenaread("D.rdf",  "RDF/XML-ABBREV"); }
    @Test public void read_15() { jenaread("D.rj", "RDF/JSON"); }
    @Test public void read_16() { jenaread("D.jsonld", "JSON-LD"); }

    @Test public void read_21a() { jenaread("D-nt",  "N-TRIPLES"); }
    @Test public void read_21b() { jenaread("D-nt",  "NTRIPLES"); }
    @Test public void read_21c() { jenaread("D-nt",  "NT"); }
    @Test public void read_21d() { jenaread("D-nt",  "N-Triples"); }

    @Test public void read_22a() { jenaread("D-ttl", "TURTLE"); }
    @Test public void read_22b() { jenaread("D-ttl", "TTL"); }

    @Test public void read_23a()  { jenaread("D-rdf", "RDF/XML"); }
    @Test public void read_23b()  { jenaread("D-rdf", "RDFXML"); }
    @Test public void read_24()   { jenaread("D-json", "RDF/JSON"); }

    @Test public void read_30()
    {
        {
            TypedInputStream in = RDFDataMgr.open(filename("D-not-TTL.ttl") );
            Model m0 = ModelFactory.createDefaultModel();
            RDFDataMgr.read(m0, in, RDFLanguages.RDFXML);
        }

        TypedInputStream in1 = RDFDataMgr.open(filename("D-not-TTL.ttl") );
        Model m1 = ModelFactory.createDefaultModel();
        m1.read(in1, null, "RDF/XML");
    }

    // test read from StringReader..
    @Test public void read_StringReader_31()
    {
        String x = "<s> <p> <p> .";

        {
            StringReader s = new StringReader(x);
            Model m = ModelFactory.createDefaultModel();
            RDFDataMgr.read(m, s, null, RDFLanguages.NTRIPLES);
        }

        StringReader s1 = new StringReader("<s> <p> <p> .");
        Model m1 = ModelFactory.createDefaultModel();
        m1.read(s1, null, "N-TRIPLES");
    }

    @Test public void read_StringReader_32()
    {
        String x = StrUtils.strjoinNL(
            "<rdf:RDF",
            "   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"",
            "   xmlns:j.0=\"http://example/\">" ,
            "  <rdf:Description rdf:about=\"http://example/s\">" ,
            "     <j.0:p rdf:resource=\"http://example/o\"/>" ,
            "   </rdf:Description>" ,
            "</rdf:RDF>");
        {
            StringReader s = new StringReader(x);
            Model m = ModelFactory.createDefaultModel();
            RDFDataMgr.read(m, s, null, RDFLanguages.RDFXML);
        }
        StringReader s1 = new StringReader(x);
        Model m = ModelFactory.createDefaultModel();
        m.read(s1, null, "RDF/XML");
    }

    // Stream opening is hardwired into jena!
    @Test public void read_base_1()
    { jenaread("D-no-base.ttl", "TTL", "http://baseuri/"); }

    @Test public void read_input_1() throws IOException
    { jenaread_stream("D.ttl", "TTL"); }

    @Test public void read_input_2() throws IOException
    { jenaread_stream("D.rdf", "RDF/XML"); }

    private static final String plainRelFnTTL = directory+"/D.ttl";
    private static final String plainRelFnRDFXML = directory+"/D.rdf";

    // Ways to pass in the filename.
    // The RDF/XML path is slightly different so test it as well.

    @Test public void read_url_1() {
        modelRead(plainRelFnTTL);
    }

    @Test public void read_url_1x() {
        modelRead(plainRelFnRDFXML);
    }

    @Test public void read_url_2() {
        modelRead("file:"+plainRelFnTTL);
    }

    @Test public void read_url_2x() {
        modelRead("file:"+plainRelFnRDFXML);
    }

    @Test public void read_url_3() {
        String cwd = Path.of(".").toAbsolutePath().normalize().toString();
        modelRead("file:"+cwd+"/"+plainRelFnTTL);
    }

    @Test public void read_url_3x() {
        String cwd = Path.of(".").toAbsolutePath().normalize().toString();
        modelRead("file:"+cwd+"/"+plainRelFnRDFXML);
    }

    @Test public void read_url_4() {
        String cwd = Path.of(".").toAbsolutePath().normalize().toString();
        String fn = "file:"+cwd+"/"+plainRelFnTTL;
        String fn2 = IRILib.filenameToIRI(fn);
        modelRead(fn2);
    }

    @Test public void read_url_4x() {
        String cwd = Path.of(".").toAbsolutePath().normalize().toString();
        String fn = "file:"+cwd+"/"+plainRelFnRDFXML;
        String fn2 = IRILib.filenameToIRI(fn);
        modelRead(fn2);
    }

    private static Model modelRead(String fn) {
        Model m = ModelFactory.createDefaultModel();
        m.read(fn);
        return m;
    }

    // -----------------------------------------

    private static String filename(String filename) { return directory+"/"+filename; }

    private static void jenaread_stream(String filename, String lang) throws IOException {
        filename = filename(filename);

        // Read with a base
        try (FileInputStream in0 = new FileInputStream(filename)) {
            Model m0 = ModelFactory.createDefaultModel();
            RDFDataMgr.read(m0, in0, "http://example/base2", RDFLanguages.nameToLang(lang));
        }

        // Read again, but without base
        try (FileInputStream in1 = new FileInputStream(filename)) {
            Model m1 = ModelFactory.createDefaultModel();
            RDFDataMgr.read(m1, in1, RDFLanguages.nameToLang(lang));
        }

        // Read via Jena API.
        Model m2 = ModelFactory.createDefaultModel();
        try (FileInputStream in2 = new FileInputStream(filename)) {
            m2.read(in2, "http://example/base3", lang);
        }

        String x = FileUtils.readWholeFileAsUTF8(filename);
        Model m3 = ModelFactory.createDefaultModel();
        m2.read(new StringReader(x), "http://example/base4", lang);
    }

    private static void jenaread(String dataurl) {
        dataurl = filename(dataurl);
        Model m = ModelFactory.createDefaultModel();
        m.read(dataurl);
        assertTrue(m.size() != 0);
    }

    private static void jenaread(String dataurl, String lang) {
        // read via WebReader to make sure the test setup is right.
        dataurl = filename(dataurl);

        Model m0 = ModelFactory.createDefaultModel();
        RDFDataMgr.read(m0, dataurl, RDFLanguages.nameToLang(lang));
        assertTrue(m0.size() != 0);

        Model m1 = ModelFactory.createDefaultModel();
        new RDFReaderFactoryRIOT().getReader(lang).read(m1, dataurl);
        assertTrue(m1.size() != 0);

        // Read via Jena model API.
        Model m2 = ModelFactory.createDefaultModel();
        // The range of names for mode.read is less - canonicalise the language
        // name.
        String x = RDFLanguages.nameToLang(lang).getName();
        m2.read(dataurl, x);
        assertTrue(m2.size() != 0);
    }

    private static void jenaread(String dataurl, String lang, String base) {
        dataurl = filename(dataurl);
        Model m1 = ModelFactory.createDefaultModel();
        Model m2 = ModelFactory.createDefaultModel();

        // This call
        RDFDataMgr.read(m1, dataurl, base, RDFLanguages.nameToLang(lang));
        // should be an implementation of:
        m2.read("file:"+dataurl, base, lang);
        assertTrue(m1.size() != 0 );
        assertTrue(m2.size() != 0 );
        assertTrue(m1.isIsomorphicWith(m2));
        // and check base processing ...
        Resource s = m1.listStatements().next().getSubject();
        assertTrue(s.getURI().startsWith("http://"));
        assertTrue(s.getURI().equals("http://baseuri/s"));
    }
}

